import React, { useState, useEffect } from 'react';
import { Drawer, message, Space } from 'antd';
import { connect, Dispatch } from 'umi';
import { ROLE_LIST,
  ROLE_ADD,
  ROLE_UPDATE,
  ROLE_DELETE,
  MENU_TREE,
  GRANT_AUTH,
  UPDATE_STATE } from '@/actions/role';
import ProCard from '@ant-design/pro-card';
import ProDescriptions, { ProDescriptionsItemProps } from '@ant-design/pro-descriptions';
import {PageContainer } from '@ant-design/pro-layout';
import AGrid, { AGridButtonCallBackModel } from '@/components/SelfComp/AGrid';
import AButton from '@/components/SelfComp/AButton';
import { ConnectState } from '@/models/connect';
import RoleQueryForm from './components/RoleQueryForm';
import AddRoleModal from './components/AddRoleModal';
import UpdateRoleModal from './components/UpdateRoleModal';
import GrantAuthModal from './components/GrantAuthModal';
import { AuthTreeData, GrantAuthItem, RoleItem } from './data';

interface RoleListProps {
  dispatch: Dispatch;
  roleList: RoleItem[],
  total: number,
  loading: boolean;
  pageSize: number;
  addLoading: boolean;
  updateLoading: boolean;
  previewLoading: boolean;
  grantLoading: boolean;
}

const EMPTY_ROLE: RoleItem = {
  roleId: '',
  roleCode: '',
  roleName: '',
  roleDesc: '',
}

const EMPTY_TREE: AuthTreeData = {
  roleId: '',
  grantKeys: [],
  menuTree: [],
}

/**
 * 角色列表管理
 * @param props 属性
 * @returns 角色列表
 */
const RoleList: React.FC<RoleListProps> = (props) => {
  const code = 'role-list';
  const { roleList, loading, total, addLoading, updateLoading, grantLoading } = props;
  const [addModalVisible, handleAddModalVisible] = useState<boolean>(false);
  const [updateModalVisible, handleUpdateModalVisible] = useState<boolean>(false);
  const [roleAuthModalVisible, handleRoleAuthModalVisible] = useState<boolean>(false);
  const [row, setRow] = useState<RoleItem>();
  const [selectedRowKeys, setSelectedRowKeys] = useState<React.Key[]>([]);
  const [selectedRows, setSelectedRows] = useState<RoleItem[]>([]);
  const [queryParam, setQueryParam] = useState<RoleItem>(EMPTY_ROLE);
  const [pageSize, setPageSize] = useState<number>(10);
  const [roleFormData, setRoleFormData] = useState<RoleItem>(EMPTY_ROLE);
  const [authTreeData, setAuthTreeData] = useState<AuthTreeData>(EMPTY_TREE);
  const rowKey = (record: RoleItem) => {
    return record.roleId;
  }
  const pkField = 'roleId';
  const columns = [
    {
      title: '角色编码',
      dataIndex: 'roleCode',
      width: 150,
      render: (text: string, record: RoleItem, index: number) => {
        return <a onClick={() => setRow(record)}>{text}</a>;
      },
    },
    {
      title: '角色名称',
      dataIndex: 'roleName',
      width: 200
    },
    {
      title: '角色描述',
      dataIndex: 'roleDesc',
    },
    {
      title: '状态',
      dataIndex: 'userStates',
      width: 100,
    }
  ];

  useEffect(() => {
    console.info('RoleList.useEffect');
    fetchAllRole(1, 10, queryParam);
    return () => {
      const { dispatch } = props;
      dispatch(UPDATE_STATE({
        rows: [],
        total: 0
      }));
    }
  }, []);

  /**
   * 查询满足条件的数据字典
   */
  const handleQuery = (record: RoleItem) => {
    console.info('RoleList.handleQuery');
    console.info(record);
    const queryParam = {
      ...record
    };
    // 查询条件保存起来，方便点击页码时使用
    // setState回调方法，保证先更新state
    fetchAllRole(1, pageSize, queryParam);
  }

  const handleReset = () => {
    // 是否清空表格
  }

  /**
   * 分页查询系统参数信息
   * @param {*} pageNum 页码
   * @param {*} pageSize 每页记录条数
   */
  const fetchAllRole = (pageNum: number, pageSize: number, queryParam: RoleItem) => {
    const { dispatch } = props;
    dispatch(ROLE_LIST({
      ...queryParam,
      pageSize,
      pageNum
    }));
  }

  /**
   * 删除用户，暂时只支持单笔删除
   * @param userId 用户id
   */
  const deleteRoles = async (roleIds: React.Key[]) => {
    const { dispatch } = props;
    const res = await dispatch(ROLE_DELETE(roleIds));
    if (res) {
      dispatch(ROLE_LIST({
        ...queryParam,
        pageSize,
        pageNum: 1,
      }));
    }
  }

  /**
   * 处理按钮点击回调事件
   * @param {*} payload 数据包
   */
  const handleBtnCallBack = (callBackModel: AGridButtonCallBackModel<RoleItem>) => {
    console.log('handleBtnCallBack');
    console.log(callBackModel);
    // btn 按钮
    // keys 表格勾选数组
    const { btn } = callBackModel;
    const { alias } = btn;
    // 新增
    if (alias === 'add') {
      handleAddModalVisible(true);
      return;
    }
    // 修改
    if (alias === 'edit') {
      const { rows } = callBackModel;
      setRoleFormData(rows[0]);
      handleUpdateModalVisible(true);
      return;
    }
    // 删除
    if (alias === 'delete') {
      const { keys } = callBackModel;
      // 调用删除服务，删除勾选数据
      deleteRoles(keys);
      return;
    }
  }

  /**
   * 表格勾选回调函数
   * @param {*} rows 表格选中数据集合
   */
  const onSelectRow = (keys: React.Key[], rows: RoleItem[]) => {
    console.info('onSelectRow', keys);
    setSelectedRowKeys(keys);
    setSelectedRows(rows);
  };

  /**
   * 页码改变的回调，参数是改变后的页码及每页条数
   * @param page 改变后的页码，上送服务器端
   * @param pageSize 每页数据条数
   */
  const onPageNumAndSizeChange = (page: number, pageSize: number) => {
    console.log(page, pageSize);
    setPageSize(pageSize);
    fetchAllRole(page, pageSize, queryParam);
  };

  const renderLeftButton = () => {
    const { previewLoading } = props;
    return (
      <>
        <AButton
          code='grantAuth'
          pageCode='role-list'
          name='权限分配'
          loading={previewLoading}
          onClick={openRoleAuthModal} />
      </>
    );
  }

  /**
   * 角色授权，打开角色授权窗口
   */
  const openRoleAuthModal = async () => {
    // 表格选中内容
    console.info('openRoleAuthModal');
    if (selectedRowKeys.length === 0) {
      message.warn('请先选择一条数据!');
      return;
    }
    if (selectedRowKeys.length > 1) {
      message.warn('只能选择一条数据!');
      return;
    }
    // 获取角色id
    const roleId = selectedRowKeys[0];
    console.info('roleId', roleId);
    const { dispatch } = props;
    const res = await dispatch(MENU_TREE({
      roleId
    }));
    // console.info(res);
    if (res) {
      // 查询菜单权限树，并根据勾选角色ID对应已分配的权限
      // 这里试试dispatch的回调方法
      // 只有查询成功才会弹窗
      const { result } = res;
      const { grantKeys, menuTree } = result;
      const authTreeData = {
        roleId,
        grantKeys,
        menuTree
      };
      handleRoleAuthModalVisible(true);
      setAuthTreeData(authTreeData);
    }
  }

  /**
   * 授权窗口确认按钮
   * @param {*} record 授权树选中菜单列表
   */
  const handleGrantModal = async (record: GrantAuthItem) => {
    console.log('handleGrantModalOk', record);
    const { dispatch } = props;
    const res = await dispatch(GRANT_AUTH(record));
    if (res) {
      handleRoleAuthModalVisible(false);
      setAuthTreeData(EMPTY_TREE);
    }
  }

  const handleGrantModalCancel = () => {
    console.log('handleGrantModalCancel');
    handleRoleAuthModalVisible(false);
    setAuthTreeData(EMPTY_TREE);
  }

  const handleAddModal = async (record: RoleItem) => {
    console.log(record);
    const { dispatch } = props;
    console.info(dispatch);
    const res = await dispatch(ROLE_ADD(record));
    console.info(res);
    if (res) {
      handleAddModalVisible(false);
      fetchAllRole(1, pageSize, queryParam);
    }
  }

  const handleAddModalCancel = () => {
    handleAddModalVisible(false);
  };

  /**
   * 更新面板的确定事件
   * @param {*} record 更新表单
   */
  const handleUpdateModal = async (record: RoleItem) => {
    console.log('handleUpdateModalOk');
    console.log(record);
    console.info(roleFormData);
    const { dispatch } = props;
    const res = await dispatch(ROLE_UPDATE(record));
    console.info(res);
    if (res) {
      handleUpdateModalVisible(false);
      setRoleFormData(EMPTY_ROLE);
      fetchAllRole(1, pageSize, queryParam);
    }
  }

  const handleUpdateModalCancel = () => {
    handleUpdateModalVisible(false);
    setRoleFormData(EMPTY_ROLE);
  };

  return (
    <PageContainer>
      <Space direction='vertical' size='middle' style={{ display: 'flex' }}>
        <ProCard title="查询条件" headerBordered>
          <RoleQueryForm
            colon={false}
            loading={loading}
            onSubmit={(record) => {
              setQueryParam(record);
              handleQuery(record);
            }}
            onReset={handleReset}
          />
        </ProCard>
        <ProCard>
          <AGrid
            code={code}
            btnCallBack={handleBtnCallBack}
            delConfirmMsg='确定删除选中记录？请注意，若有用户已分配该角色，将一并删除！'
            renderLeftButton={renderLeftButton}
            columns={columns}
            rowKey={rowKey}
            pkField={pkField}
            dataSource={roleList}
            loading={loading}
            total={total}
            onSelectRow={onSelectRow}
            onPageNumAndSizeChange={onPageNumAndSizeChange}
          />
        </ProCard>
      </Space>
      {
        !addModalVisible ? null :
        <AddRoleModal
          colon={false}
          modalTitle='新增角色'
          modalWidth={1000}
          modalVisible={addModalVisible}
          loading={addLoading}
          onHandlerOK={handleAddModal}
          onHandlerCancel={handleAddModalCancel}
        />
      }
      {
        !updateModalVisible ? null :
        <UpdateRoleModal
          colon={false}
          modalTitle=''
          modalWidth={1000}
          modalVisible={updateModalVisible}
          flag='edit'
          loading={updateLoading}
          formData={roleFormData}
          onHandlerOK={handleUpdateModal}
          onHandlerCancel={handleUpdateModalCancel}
        />
      }
      {
        !roleAuthModalVisible ? null :
        <GrantAuthModal
          colon={false}
          modalTitle='分配权限'
          modalWidth={600}
          modalVisible={roleAuthModalVisible}
          flag='edit'
          loading={grantLoading}
          formData={authTreeData}
          onHandlerOK={handleGrantModal}
          onHandlerCancel={handleGrantModalCancel}
        />
      }
      <Drawer
        width={600}
        open={!!row}
        onClose={() => {
          setRow(undefined);
        }}
        closable={false}
      >
        {row?.roleId && (
          <ProDescriptions<RoleItem>
            column={2}
            title={row?.roleName}
            request={async () => ({
              data: row || {},
            })}
            params={{
              id: row?.roleId,
            }}
            columns={columns as ProDescriptionsItemProps<RoleItem>[]}
          />
        )}
      </Drawer>
    </PageContainer>
  );
};


export default connect((state: ConnectState) => ({
  total: state.roles.total,
  roleList: state.roles.rows,
  loading: state.loading.effects['roles/fetchAllRole'],
  addLoading: state.loading.effects['roles/addRole'],
  updateLoading: state.loading.effects['roles/updateRole'],
  previewLoading: state.loading.effects['roles/fetchMenuTreeByRole'],
  grantLoading: state.loading.effects['roles/grantAuths'],
}))(RoleList);